use crate::window::{UIState, Window};

use super::{options::Options, BaseFitneser, Fitneser};
use log::debug;
use std::{
  error::Error,
  sync::{mpsc::Sender, Arc, Mutex},
};

pub struct Walk {
  _super: BaseFitneser,
}

impl Walk {
  pub fn new(mutex: Arc<Mutex<bool>>) -> Self {
    Walk {
      _super: BaseFitneser::new(mutex),
    }
  }
}

impl Fitneser for Walk {
  fn init(&mut self, opts: &Options, asset_path: String) -> Result<bool, Box<dyn Error>> {
    self._super.setup(opts, asset_path);
    Ok(true)
  }

  /// 运行练体
  /// ### 返回值
  /// * `true` 外部正常结束
  /// * `false` 异常结束
  fn run(&mut self, win: &Window, msg_tx: &Sender<String>) -> Result<bool, Box<dyn Error>> {
    let mut _state = 0;
    self.reset(win)?;
    self._super.try_repair(win)?;
    'outter: loop {
      // if self._super.exit_no_die(win)? {
      //   let _ = msg_tx.send(format!("生命中低 退出游戏"));
      //   break;
      // }
      if _state == 0 {
        _state = self._super.fetch_state(win)?;
      }
      // 放下箱子并吃东西
      if _state != 0 {
        let _ = msg_tx.send(format!("当前状态: {}", _state));

        // 如果需要退出 先捡起包 免得丢失
        if _state & (1 << 8) == 256 {
          self.pickup(win)?;
          self.stop(win)?;
          self._super.exit_to_lobby(win)?;
          return Ok(false);
        }
        if !self._super.ensure_base(win, _state)? {
          break;
        }
        // 温度过高
        if _state & 16 == 16 {
          let _ = msg_tx.send(format!("温度过高 冷静 1 分钟"));

          for _ in 0..60 {
            win.sleep(1000);
            if !self._super.is_running() {
              break 'outter;
            }
          }
        }
      }
      _state = 0;
      // 尝试移动到后方中心
      self.back_center(win)?;
      // 检查掉线
      if self._super.check_lost(win)? {
        self.stop(win)?;
        if !self._super.handle_lost(win)? {
          self._super.stop_running();
          let _ = msg_tx.send(format!("掉线无法重连"));
          return Ok(false);
        }
        continue;
      }
      // 开始循环走 两分钟一循环
      // 拿起重物
      let _ = msg_tx.send(format!("开始移动"));
      self.pickup(win)?;
      self._super.look_status(win)?;
      let mut _ticks = 0;
      loop {
        if !self._super.is_running() {
          break 'outter;
        }
        // 前
        win.press_key("w")?;
        win.release_key("s")?;
        // win.sleep(500);
        // win.release_key("a")?;
        win.sleep(1800);
        // win.press_key("d")?;
        win.press_key("s")?;
        win.release_key("w")?;
        // win.sleep(500);
        // win.release_key("d")?;
        win.sleep(1800);
        _ticks += 1;
        if _ticks % 40 == 0 {
          // win.release_key("s")?;
          if self._super.try_repair(win)? {
            break;
          }
          _state = self._super.fetch_state(win)?;
          if _state == 0 {
            self._super.look_status(win)?;
          } else {
            break;
          }
        }
        // win.press_key("a")?;
        // win.release_key("s")?;
      }
    }
    // 停止
    self.stop(win)?;
    Ok(true)
  }
}

impl Walk {
  fn reset(&self, win: &Window) -> Result<(), Box<dyn Error>> {
    win.ensure_ui(UIState::Default, 0)?;
    win.tap_key("space")?;
    win.sleep(1500);
    win.mouse_click_l()?;
    win.sleep(1000);
    win.tap_key("c")?;
    win.sleep(1000);
    Ok(())
  }

  /// 尝试走到后边中心
  fn back_center(&self, win: &Window) -> Result<(), Box<dyn Error>> {
    if !self._super.is_running() {
      return Ok(());
    }
    win.press_key("w")?;
    win.sleep(500);
    win.release_key("w")?;
    if !self._super.is_running() {
      return Ok(());
    }
    win.press_key("d")?;
    win.sleep(1000 * 2);
    win.release_key("d")?;
    if !self._super.is_running() {
      return Ok(());
    }
    win.press_key("a")?;
    win.sleep(1000);
    win.release_key("a")?;
    if !self._super.is_running() {
      return Ok(());
    }
    win.press_key("s")?;
    win.sleep(1000 * 2);
    win.release_key("s")?;
    Ok(())
  }

  fn stop(&self, win: &Window) -> Result<(), Box<dyn Error>> {
    win.ensure_ui(UIState::Default, 0)?;
    win.release_key("w")?;
    win.release_key("a")?;
    win.release_key("s")?;
    win.release_key("d")?;
    Ok(())
  }

  /// 拿起重物
  /// ### 拿起第二位置的容器
  fn pickup(&self, win: &Window) -> Result<bool, Box<dyn Error>> {
    if !self._super.is_running() {
      return Ok(false);
    }
    win.ensure_ui(UIState::Tab, 1)?;
    win.mouse_move_to(360 + 80, 190)?;
    win.mouse_click_r()?;
    win.sleep(125);
    win.mouse_move_to(360 + 80, 190 + 38)?;
    win.sleep(50);
    win.mouse_click_l()?;
    win.sleep(1000);
    // 蹲下
    win.ensure_ui(UIState::Default, 0)?;
    if self._super.opts.sub_type == 0 {
      win.tap_key("space")?;
      win.sleep(1500);
    }
    win.tap_key("c")?;
    win.sleep(1500);
    // 趴下
    if self._super.opts.sub_type == 1 {
      win.tap_key("x")?;
      win.sleep(1500);
    }
    Ok(true)
  }
}
